# ManyRelationDescriptor.java

    package org.codefilarete.stalactite.engine.runtime.onetomany;

    import java.util.Collection;
    import java.util.function.Supplier;
    import javax.annotation.Nullable;

    import org.codefilarete.reflection.Mutator;
    import org.codefilarete.reflection.PropertyMutator;
    import org.codefilarete.reflection.ReadWritePropertyAccessPoint;
    import org.codefilarete.stalactite.sql.result.BeanRelationFixer;
    import org.codefilarete.tool.bean.Objects;

    /**
     * Container to store information of a one-to-many relation
     *
     * @author Guillaume Mary
     */
    public class ManyRelationDescriptor<I, O, C extends Collection<O>> {

    	/** Empty setter for applying source entity to target entity (reverse side) */
    	protected static final PropertyMutator NOOP_REVERSE_SETTER = (o, i) -> {};

    	private final ReadWritePropertyAccessPoint<I, C> collectionAccessPoint;

    	private final Supplier<C> collectionFactory;

    	private final PropertyMutator<O, I> reverseSetter;

    	protected BeanRelationFixer<I, O> relationFixer;

    	private final boolean maintainAssociationOnly;

    	private final boolean orphanRemoval;

    	/**
    	 * @param collectionAccessPoint collection accessor
    	 * @param collectionFactory collection factory
    	 * @param reverseSetter
    	 */
    	public ManyRelationDescriptor(ReadWritePropertyAccessPoint<I, C> collectionAccessPoint,
    	                              Supplier<C> collectionFactory,
    	                              @Nullable PropertyMutator<O, I> reverseSetter,
    	                              boolean maintainAssociationOnly,
    								  boolean orphanRemoval) {
    		this(collectionAccessPoint,
    				collectionFactory,
    				reverseSetter,
    				BeanRelationFixer.of(collectionAccessPoint, collectionFactory, Objects.preventNull(reverseSetter, (Mutator<O, I>) NOOP_REVERSE_SETTER)), maintainAssociationOnly, orphanRemoval
    		);
    	}

    	public ManyRelationDescriptor(ReadWritePropertyAccessPoint<I, C> collectionAccessPoint,
    	                              Supplier<C> collectionFactory,
    	                              PropertyMutator<O, I> reverseSetter,
    	                              BeanRelationFixer<I, O> relationFixer,
    	                              boolean maintainAssociationOnly,
    								  boolean orphanRemoval) {
    		this.collectionAccessPoint = collectionAccessPoint;
    		this.collectionFactory = collectionFactory;
    		this.reverseSetter = reverseSetter;
    		this.relationFixer = relationFixer;
    		this.maintainAssociationOnly = maintainAssociationOnly;
    		this.orphanRemoval = orphanRemoval;
    	}

    	public ReadWritePropertyAccessPoint<I, C> getCollectionAccessPoint() {
    		return collectionAccessPoint;
    	}

    	public Supplier<C> getCollectionFactory() {
    		return collectionFactory;
    	}

    	/**
    	 * Gives the setter for source bean on the owning side.
    	 *
    	 * @return null if no setter given at construction time
    	 */
    	@Nullable
    	public PropertyMutator<O, I> getReverseSetter() {
    		return reverseSetter;
    	}

    	public BeanRelationFixer<I, O> getRelationFixer() {
    		return relationFixer;
    	}

    	public boolean isMaintainAssociationOnly() {
    		return maintainAssociationOnly;
    	}

    	public boolean isOrphanRemoval() {
    		return orphanRemoval;
    	}
    }